package com.hrzyit.base.utils

import android.util.Log
import org.jivesoftware.smack.ConnectionConfiguration
import org.jivesoftware.smack.MessageListener
import org.jivesoftware.smack.SmackException.NoResponseException
import org.jivesoftware.smack.SmackException.NotConnectedException
import org.jivesoftware.smack.XMPPException
import org.jivesoftware.smack.XMPPException.XMPPErrorException
import org.jivesoftware.smack.chat.ChatManager
import org.jivesoftware.smack.chat.ChatManagerListener
import org.jivesoftware.smack.packet.Message
import org.jivesoftware.smack.roster.Roster
import org.jivesoftware.smack.roster.RosterEntry
import org.jivesoftware.smack.roster.RosterGroup
import org.jivesoftware.smack.tcp.XMPPTCPConnection
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration
import org.jivesoftware.smackx.iqregister.AccountManager
import org.jivesoftware.smackx.muc.MultiUserChat
import org.jivesoftware.smackx.muc.MultiUserChatManager
import org.jivesoftware.smackx.pubsub.*
import org.jivesoftware.smackx.vcardtemp.VCardManager
import org.jivesoftware.smackx.vcardtemp.packet.VCard
import org.jivesoftware.smackx.xdata.FormField
import org.jivesoftware.smackx.xdata.packet.DataForm
import org.jxmpp.stringprep.XmppStringprepException
import java.util.*


class SmackUtil {

    private lateinit var connection: XMPPTCPConnection

    private lateinit var userName: String

    private lateinit var password: String

    private var serverDomain: String? = "218.246.5.251" // OpenFire IP

    private var port: Int = 5222

    private var serverName: String? = "218.246.5.251" // OpenFire IP

    /**
     * 获取用户属性名称
     * @return
     * @throws Exception
     */
    val accountInfo: List<String>
        @Throws(Exception::class)
        get() {
            val list = ArrayList<String>()
            val manager = AccountManager.getInstance(connection)
            manager.sensitiveOperationOverInsecureConnection(true)
            val set = manager.accountAttributes
            list.addAll(set)
            return list
        }

    /**
     * 获取所有组
     * @return
     * @throws Exception
     */
    val groups: List<RosterGroup>
        @Throws(Exception::class)
        get() {
            val grouplist = ArrayList<RosterGroup>()
            val roster = Roster.getInstanceFor(connection)
            val rosterGroup = roster.groups
            val i = rosterGroup.iterator()
            while (i.hasNext()) {
                grouplist.add(i.next())
            }
            return grouplist
        }

    /**
     * 获取全部好友
     * @return
     * @throws Exception
     */
    val allEntries: List<RosterEntry>
        @Throws(Exception::class)
        get() {
            val roster = Roster.getInstanceFor(connection)
            val Entrieslist = ArrayList<RosterEntry>()
            val rosterEntry = roster.entries
            val i = rosterEntry.iterator()
            while (i.hasNext()) {
                Entrieslist.add(i.next())
            }
            return Entrieslist
        }

    /**
     * 此构造函数 仅连接
     * @param serverDomain openfire服务器 域名或 IP
     * @param port  端口默认:5222
     */
    constructor(serverDomain: String, port: Int = 5222) {
        this.serverDomain = serverDomain
        this.serverName = serverDomain
        this.port = port
    }

    /**
     * 构造函数 此构造函数直接登录
     * @param userName  用户名
     * @param password  密码
     * @param serverDomain  openfire服务器 域名或 IP
     * @param port  端口默认:5222
     */
    constructor(userName: String, password: String, serverDomain: String, port: Int = 5222) {
        this.userName = userName
        this.password = password
        this.serverDomain = serverDomain
        this.serverName = serverDomain
        this.port = port
        try {
            if (connection == null) {
                getConnectionLogin(userName, password, serverDomain, port)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    /**
     * Openfire 连接
     * @return
     */
    fun getConnection(): XMPPTCPConnection? {
        if (connection != null) {
            return connection
        }
        try {
            val configBuilder = XMPPTCPConnectionConfiguration
                .builder()
            configBuilder.setHost(serverDomain)
            configBuilder.setPort(port!!)
            //configBuilder.setUsernameAndPassword(userName, password);
            //configBuilder.setXmppDomain(serverDomain);
            configBuilder.setServiceName(serverDomain)
            configBuilder.setSendPresence(true)
            configBuilder.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)

            connection = XMPPTCPConnection(configBuilder.build())
            //connection.setReplyTimeout(60000l);
            connection.packetReplyTimeout = 60000L
            // 连接服务器
            connection.connect()
            Log.e("SmackUtil->", "openfire 已连接")
        } catch (e: Exception) {
            e.printStackTrace()
        }

        return connection
    }

    /**
     * Openfire 连接
     * @param serverDomain 域名
     * @param port 端口号
     */
    fun getConnection(serverDomain: String, port: Int?) {
        try {
            val configBuilder = XMPPTCPConnectionConfiguration
                .builder()
            configBuilder.setHost(serverDomain)
            configBuilder.setPort(port!!)
            //configBuilder.setUsernameAndPassword(userName, password);
            //configBuilder.setXmppDomain(serverDomain);
            configBuilder.setServiceName(serverDomain)
            configBuilder.setSendPresence(true)
            configBuilder.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)

            connection = XMPPTCPConnection(configBuilder.build())
            //connection.setReplyTimeout(60000l);
            connection.packetReplyTimeout = 60000L
            // 连接服务器
            connection.connect()
            Log.e("SmackUtil->", "openfire 已连接")
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    /**
     * 登录
     * @param userName 用户名
     * @param password 密码
     * @return
     */
    fun loginOpenFire(userName: String, password: String): Boolean {
        var done: Boolean
        try {
            this.userName = userName
            this.password = password
            getConnection()!!.login(userName, password)
            done = true
        } catch (e: Exception) {
            e.printStackTrace()
            done = false
        }

        return done
    }

    /**
     * openfire 获取连接 并登录
     * @param userName
     * @param password
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun getConnectionLogin(userName: String, password: String, serverDomain: String, port: Int?) {
        try {
            val configBuilder = XMPPTCPConnectionConfiguration
                .builder()
            configBuilder.setHost(serverDomain)
            configBuilder.setPort(port!!)
            configBuilder.setUsernameAndPassword(userName, password)
            configBuilder.setServiceName(serverDomain)
            //configBuilder.setXmppDomain(serverDomain);
            //设置离线状态 false会导致IncomeListener无法触发
            configBuilder.setSendPresence(true)
            //禁用SSL连接
            configBuilder.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
            //启用调试模式
            //configBuilder.setDebuggerEnabled(true);
            //需要经过同意才可以添加好友
            //Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.manual);

            connection = XMPPTCPConnection(configBuilder.build())
            //connection.setReplyTimeout(60000l);
            //connection.setFromMode(XMPPTCPConnection.FromMode.USER);
            // 连接服务器
            connection.connect()
            Log.e("SmackUtil->", "openfire 已连接")
            // 登录服务器
            connection.login()
            Log.e("SmackUtil->", "$userName 已登录")

        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    /**
     * openfire 注销连接
     */
    fun disConnented() {
        if (connection != null) {
            connection.disconnect()
        }
        Log.e("SmackUtil->", "openfire 已断开")
    }

    /**
     * 注册一个新用户
     * @param userName 用户名
     * @param password 密码
     * @param attr  用户资料
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun registerAccount(userName: String, password: String, attr: Map<String, String>?): Boolean {
        val manager = AccountManager.getInstance(connection)
        manager.sensitiveOperationOverInsecureConnection(true)
        //Localpart l_username = Localpart.from(userName);
        if (attr == null) {
            //manager.createAccount(l_username, password);
            manager.createAccount(userName, password)
        } else {
            //manager.createAccount(l_username, password, attr);
            manager.createAccount(userName, password, attr)
        }

        return true
    }

    /**
     * 修改当前登陆用户密码
     * @param password
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun changePassword(password: String): Boolean {
        val manager = AccountManager.getInstance(connection)
        manager.sensitiveOperationOverInsecureConnection(true)
        manager.changePassword(password)
        return true
    }

    /**
     * 删除当前登录用户
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun deleteAccount(): Boolean {
        val manager = AccountManager.getInstance(connection)
        manager.sensitiveOperationOverInsecureConnection(true)
        manager.deleteAccount()
        return true
    }

    /**
     * 添加分组
     * @param groupName
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun addGroup(groupName: String): Boolean {
        val roster = Roster.getInstanceFor(connection)
        roster.createGroup(groupName)
        return true

    }

    /**
     * 获取指定分组的好友
     * @param groupName
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun getEntriesByGroup(groupName: String): List<RosterEntry> {
        val roster = Roster.getInstanceFor(connection)
        val entrieslist = ArrayList<RosterEntry>()
        val rosterGroup = roster.getGroup(groupName)
        val rosterEntry = rosterGroup.entries
        val i = rosterEntry.iterator()
        while (i.hasNext()) {
            entrieslist.add(i.next())
        }
        return entrieslist
    }

    /**
     * 获取用户VCard信息
     * @param userName
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun getUserVCard(userName: String): VCard {
        //VCard vcard = new VCard();
        //EntityBareJid jid = JidCreate.entityBareFrom(userName + "@" + this.serverName);
        val jid = userName + "@" + this.serverName
        val vcardManager = VCardManager.getInstanceFor(connection)
//vcard.load(connection, jid);
        return vcardManager.loadVCard(jid)
    }

    /**
     * 添加好友 无分组
     * @param userName
     * @param name
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun addUser(userName: String, name: String): Boolean {
        val roster = Roster.getInstanceFor(connection)
        //EntityBareJid jid = JidCreate.entityBareFrom(userName + "@" + this.serverName);
        val jid = userName + "@" + this.serverName
        roster.createEntry(jid, name, null)
        return true
    }

    /**
     * 添加好友 有分组
     * @param userName
     * @param name
     * @param groupName
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun addUser(userName: String, name: String, groupName: String): Boolean {
        val roster = Roster.getInstanceFor(connection)
        //EntityBareJid jid = JidCreate.entityBareFrom(userName + "@" + this.serverName);
        val jid = userName + "@" + this.serverName
        roster.createEntry(jid, name, arrayOf(groupName))
        return true
    }

    /**
     * 删除好友
     * @param userName
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun removeUser(userName: String): Boolean {
        val roster = Roster.getInstanceFor(connection)
        //EntityBareJid jid = JidCreate.entityBareFrom(userName + "@" + this.serverName);
        val jid = userName + "@" + this.serverName
        val entry = roster.getEntry(jid)
        Log.e("SmackUtil->", "删除好友：$userName")
        Log.e("SmackUtil->", "User.${roster.getEntry(jid)}")
        roster.removeEntry(entry)
        return true
    }

    /**
     * 创建发布订阅节点
     * @param nodeId
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun createPubSubNode(nodeId: String): Boolean {
        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        // Create the node
        val leaf = mgr.createNode(nodeId)
        val form = ConfigureForm(DataForm.Type.submit)
        form.accessModel = AccessModel.open
        form.isDeliverPayloads = true
        form.isNotifyRetract = true
        form.setPersistentItems(true)
        form.publishModel = PublishModel.open
        form.maxItems = 10000000// 设置最大的持久化消息数量

        leaf.sendConfigurationForm(form)
        return true
    }

    /**
     * 创建发布订阅节点
     * @param nodeId
     * @param title
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun createPubSubNode(nodeId: String, title: String): Boolean {
        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        // Create the node
        val leaf = mgr.createNode(nodeId)
        val form = ConfigureForm(DataForm.Type.submit)
        form.accessModel = AccessModel.open
        form.isDeliverPayloads = true
        form.isNotifyRetract = true
        form.setPersistentItems(true)
        form.publishModel = PublishModel.open
        form.title = title
        form.bodyXSLT = nodeId
        form.maxItems = 10000000// 设置最大的持久化消息数量
        form.maxPayloadSize = 1024 * 12//最大的有效载荷字节大小
        leaf.sendConfigurationForm(form)
        return true
    }

    /**
     * 删除订阅
     * @param nodeId
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun deletePubSubNode(nodeId: String): Boolean {
        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        mgr.deleteNode(nodeId)
        return true
    }

    /**
     * 发布消息
     * @param nodeId 主题ID
     * @param eventId 事件ID
     * @param messageType 消息类型：publish（发布）/receipt（回执）/state（状态）
     * @param messageLevel 0/1/2
     * @param messageSource 消息来源
     * @param messageCount 消息数量
     * @param packageCount 总包数
     * @param packageNumber 当前包数
     * @param createTime 创建时间 2018-06-07 09:43:06
     * @param messageContent 消息内容
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun publish(
        nodeId: String, eventId: String, messageType: String, messageLevel: Int, messageSource: String,
        messageCount: Int, packageCount: Int, packageNumber: Int, createTime: String, messageContent: String
    ): Boolean {

        if (messageContent.length > 1024 * 10) {
            throw Exception("消息内容长度超出1024*10，需要进行分包发布")
        }
        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        var node: LeafNode? = null

        node = mgr.getNode(nodeId)

        val xml = StringBuffer()
        xml.append("<pubmessage xmlns='pub:message'>")
        xml.append("<nodeId>$nodeId</nodeId>")
        xml.append("<eventId>$eventId</eventId>")
        xml.append("<messageType>$messageType</messageType>")
        xml.append("<messageLevel>$messageLevel</messageLevel>")
        xml.append("<messageSource>$messageSource</messageSource>")
        xml.append("<messageCount>$messageCount</messageCount>")
        xml.append("<packageCount>$packageCount</packageCount>")
        xml.append("<packageNumber>$packageNumber</packageNumber>")
        xml.append("<createTime>$createTime</createTime>")
        xml.append("<messageContent>$messageContent</messageContent>")
        xml.append("</pubmessage>")

        val payload = SimplePayload("pubmessage", "pub:message", xml.toString().toLowerCase())
        //SimplePayload payload = new SimplePayload(xml.toString().toLowerCase());
        val item = PayloadItem(System.currentTimeMillis().toString() + "", payload)
        node!!.publish(item)
        return true
    }

    /**
     * 订阅主题
     * @param nodeId
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun subscribe(nodeId: String): Boolean {

        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        // Get the node
        val node = mgr.getNode<LeafNode>(nodeId)
        val subscriptionForm = SubscribeForm(DataForm.Type.submit)
        subscriptionForm.isDeliverOn = true
        subscriptionForm.digestFrequency = 5000
        subscriptionForm.isDigestOn = true
        subscriptionForm.isIncludeBody = true

        val subscriptions = node.subscriptions

        var flag = true
        for (s in subscriptions) {
            //TODO ?? 下一句从未执行
            //if (s.getJid().toString().equals(connection.getUser().asEntityBareJidString().toLowerCase())) {// 已订阅过
            if (s.jid.toString() == "$userName@$serverDomain") {// 已订阅过
                flag = false
                break
            }
        }
        if (flag) {// 未订阅，开始订阅
            node.subscribe(userName + "@" + this.serverName, subscriptionForm)
        }
        return true
    }

    /**
     * 获取订阅的全部主题
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun querySubscriptions(): List<Subscription> {
        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        return mgr.subscriptions
    }

    /**
     * 获取订阅节点的配置信息
     * @param nodeId
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun getConfig(nodeId: String): ConfigureForm {
        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        val node = mgr.getNode<LeafNode>(nodeId)
        return node.nodeConfiguration
    }

    /**
     * 获取订阅主题的全部历史消息
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun queryHistoryMeassage(): List<Item> {
        val result = ArrayList<Item>()
        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        val subs = mgr.subscriptions
        if (subs != null && subs.size > 0) {
            for (sub in subs) {
                val nodeId = sub.node
                val node = mgr.getNode<LeafNode>(nodeId)
                val list = node.getItems<Item>()
                result.addAll(list)
            }
        }

        /*
		 * for (Item item : result) { System.out.Log.e("SmackUtil->",item.toXML()); }
		 */
        return result
    }

    /**
     * 获取指定主题的全部历史消息
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun queryHistoryMeassage(nodeId: String): List<Item> {
        val result = ArrayList<Item>()
        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        val node = mgr.getNode<LeafNode>(nodeId)
        val list = node.getItems<Item>()
        result.addAll(list)

        /*
		 * for (Item item : result) { System.out.Log.e("SmackUtil->",item.toXML()); }
		 */
        return result
    }

    /**
     * 获取指定主题指定数量的历史消息
     * @param nodeId
     * @param num
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun queryHistoryMeassage(nodeId: String, num: Int): List<Item> {
        val result = ArrayList<Item>()
        //PubSubManager mgr = PubSubManager.getInstance(connection);
        val mgr = PubSubManager(connection)
        val node = mgr.getNode<LeafNode>(nodeId)
        val list = node.getItems<Item>(num)
        result.addAll(list)

        /*
		 * for (Item item : result) { System.out.Log.e("SmackUtil->",item.toXML()); }
		 */
        return result
    }

    /**
     * 向指定用户发送消息
     * @param username
     * @param message
     * @throws Exception
     */
    @Throws(Exception::class)
    fun sendMessage(username: String, message: String) {
        val chatManager = ChatManager.getInstanceFor(connection)
        //EntityBareJid jid = JidCreate.entityBareFrom(username + "@" + serverName);
        val jid = "$username@$serverName"
        val chat = chatManager.createChat(jid)
        //Chat chat = chatManager.chatWith(jid);
        val newMessage = Message(jid, Message.Type.chat)
        newMessage.body = message
        chat.sendMessage(newMessage)
        //chat.send(message);
    }

    /**
     * 添加聊天消息监听
     * @param chatManagerListener
     * @throws Exception
     */
    @Throws(Exception::class)
    fun addChatMessageListener(chatManagerListener: ChatManagerListener) {
        val chatManager = ChatManager.getInstanceFor(connection)
        chatManager.addChatListener(chatManagerListener)
    }

    /**
     * 断开连接
     */
    fun close() {
        connection.disconnect()
    }

    /**
     * 创建群聊聊天室
     * @param roomName  聊天室名字
     * @param nickName  创建者在聊天室中的昵称
     * @param password  聊天室密码
     * @return
     */
    @Throws(Exception::class)
    fun createChatRoom(roomName: String, nickName: String, password: String?): MultiUserChat? {
        val muc: MultiUserChat
        try {
            //EntityBareJid jid = JidCreate.entityBareFrom(roomName + "@conference." + this.serverDomain);
            val jid = roomName + "@conference." + this.serverDomain
            // 创建一个MultiUserChat
            muc = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(jid)

            //Resourcepart r = Resourcepart.from(nickName);

            // 创建聊天室
            //@SuppressWarnings("unused")
            //MucCreateConfigFormHandle isCreated = muc.create(nickName); //muc.createOrJoin(r);
            muc.create(nickName)
            //if (true) {
            // 获得聊天室的配置表单
            val form = muc.configurationForm
            // 根据原始表单创建一个要提交的新表单。
            val submitForm = form.createAnswerForm()
            // 向要提交的表单添加默认答复
            val fields = form.fields
            var i = 0
            while (fields != null && i < fields.size) {
                if (FormField.Type.hidden != fields[i].type && fields[i].variable != null) {
                    // 设置默认值作为答复
                    submitForm.setDefaultAnswer(fields[i].variable)
                }
                i++
            }
            // 设置聊天室的新拥有者
            val owners = ArrayList<String>()
            connection.user
            //owners.add(connection.getUser().asEntityBareJidString());// 用户JID
            owners.add(userName + "@" + this.serverDomain)
            submitForm.setAnswer("muc#roomconfig_roomowners", owners)
            //房间管理员
            //submitForm.setAnswer("muc#roomconfig_roomadmins", admins);
            val admins = ArrayList<String>()
            admins.add("孟庆帅@" + this.serverDomain!!)// 用户JID
            submitForm.setAnswer("muc#roomconfig_roomadmins", admins)

            // 设置聊天室是持久聊天室，即将要被保存下来
            submitForm.setAnswer("muc#roomconfig_persistentroom", true)
            // 房间仅对成员开放
            submitForm.setAnswer("muc#roomconfig_membersonly", false)
            //房间名称
            //submitForm.setAnswer("muc#roomconfig_roomname",roomname);
            //房间描述
            //submitForm.setAnswer("muc#roomconfig_roomdesc",desc);
            // 允许占有者邀请其他人
            submitForm.setAnswer("muc#roomconfig_allowinvites", true)
            if (password != null && password.length != 0) {
                // 进入是否需要密码
                submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true)
                // 设置进入密码
                submitForm.setAnswer("muc#roomconfig_roomsecret", password)
            }
            // 能够发现占有者真实 JID 的角色
            // submitForm.setAnswer("muc#roomconfig_whois", "anyone");
            // 登录房间对话
            submitForm.setAnswer("muc#roomconfig_enablelogging", true)
            // 仅允许注册的昵称登录
            submitForm.setAnswer("x-muc#roomconfig_reservednick", true)
            // 允许使用者修改昵称
            submitForm.setAnswer("x-muc#roomconfig_canchangenick", false)
            // 允许用户注册房间
            submitForm.setAnswer("x-muc#roomconfig_registration", false)
            // 发送已完成的表单（有默认值）到服务器来配置聊天室
            muc.sendConfigurationForm(submitForm)

            //}
        } catch (e: XMPPException) {
            e.printStackTrace()
            return null
        }

        return muc
    }

    /**
     * 创建群聊聊天室
     * @param roomName
     * @param nickName
     * @param whistleList
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun createChatRoom(roomName: String, nickName: String, whistleList: List<String>): MultiUserChat? {
        val muc: MultiUserChat
        try {
            //EntityBareJid jid = JidCreate.entityBareFrom(roomName + "@conference." + this.serverDomain);
            val jid = roomName + "@conference." + this.serverDomain
            // 创建一个MultiUserChat
            muc = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(jid)

            //Resourcepart r = Resourcepart.from(nickName);

            // 创建聊天室
            //@SuppressWarnings("unused")
            //MucCreateConfigFormHandle isCreated = muc.create(nickName); //muc.createOrJoin(r);
            muc.create(nickName)
            //if (true) {
            // 获得聊天室的配置表单
            val form = muc.configurationForm
            // 根据原始表单创建一个要提交的新表单。
            val submitForm = form.createAnswerForm()
            // 向要提交的表单添加默认答复
            val fields = form.fields
            var i = 0
            while (fields != null && i < fields.size) {
                if (FormField.Type.hidden != fields[i].type && fields[i].variable != null) {
                    // 设置默认值作为答复
                    submitForm.setDefaultAnswer(fields[i].variable)
                }
                i++
            }
            // 设置聊天室的新拥有者
            val owners = ArrayList<String>()
            connection.user
            //owners.add(connection.getUser().asEntityBareJidString());// 用户JID
            owners.add(userName + "@" + this.serverDomain)
            submitForm.setAnswer("muc#roomconfig_roomowners", owners)
            //房间管理员
            //submitForm.setAnswer("muc#roomconfig_roomadmins", admins);
            //List<String> admins = new ArrayList<String>();
            //admins.add("孟庆帅@"+this.serverDomain);// 用户JID
            submitForm.setAnswer("muc#roomconfig_roomadmins", whistleList)

            // 设置聊天室是持久聊天室，即将要被保存下来
            submitForm.setAnswer("muc#roomconfig_persistentroom", true)
            // 房间仅对成员开放
            submitForm.setAnswer("muc#roomconfig_membersonly", false)
            //房间名称
            //submitForm.setAnswer("muc#roomconfig_roomname",roomname);
            //房间描述
            //submitForm.setAnswer("muc#roomconfig_roomdesc",desc);
            // 允许占有者邀请其他人
            submitForm.setAnswer("muc#roomconfig_allowinvites", true)
            /*if (password != null && password.length() != 0) {
				// 进入是否需要密码
				submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true);
				// 设置进入密码
				submitForm.setAnswer("muc#roomconfig_roomsecret", password);
			}*/
            // 能够发现占有者真实 JID 的角色
            // submitForm.setAnswer("muc#roomconfig_whois", "anyone");
            // 登录房间对话
            submitForm.setAnswer("muc#roomconfig_enablelogging", true)
            // 仅允许注册的昵称登录
            submitForm.setAnswer("x-muc#roomconfig_reservednick", true)
            // 允许使用者修改昵称
            submitForm.setAnswer("x-muc#roomconfig_canchangenick", false)
            // 允许用户注册房间
            submitForm.setAnswer("x-muc#roomconfig_registration", false)
            // 发送已完成的表单（有默认值）到服务器来配置聊天室
            muc.sendConfigurationForm(submitForm)

        } catch (e: XMPPException) {
            e.printStackTrace()
            return null
        }

        return muc
    }

    /**
     * 加入聊天室
     * @param roomName
     * @param nickname
     * @param password
     * @throws Exception
     */
    @Throws(Exception::class)
    fun joinMultiUserChat(roomName: String, nickname: String, password: String): MultiUserChat {
        //EntityBareJid jid = JidCreate.entityBareFrom(roomName + "@conference." + this.serverDomain);
        val jid = roomName + "@conference." + this.serverDomain
        // 创建一个MultiUserChat
        val muc = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(jid)
        // 聊天室服务将会决定要接受的历史记录数量
        //Resourcepart r = Resourcepart.from(nickname);
        //muc.join(r);
        muc.join(nickname)
        return muc
    }

    /**
     * 聊天室发送消息
     * @param roomName
     * @param msg
     * @throws Exception
     */
    @Throws(Exception::class)
    fun sendMessageMultiUserChat(roomName: String, msg: String) {
        //EntityBareJid jid = JidCreate.entityBareFrom(roomName + "@conference." + this.serverDomain);
        val jid = roomName + "@conference." + this.serverDomain
        // 创建一个MultiUserChat
        val muc = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(jid)
        muc.sendMessage(msg)
    }

    /**
     * 获取MultiUserChat
     * @param roomName
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun getMultiUserChat(roomName: String): MultiUserChat {
        //EntityBareJid jid = JidCreate.entityBareFrom(roomName + "@conference." + this.serverDomain);
        val jid = roomName + "@conference." + this.serverDomain
        // 创建一个MultiUserChat
        return MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(jid)
    }

    /**
     * 添加聊天室消息监听
     * @param roomName
     * @param messageListener
     * @throws Exception
     */
    @Throws(Exception::class)
    fun addMultiUserChatMessageListener(roomName: String, messageListener: MessageListener) {
        val muc = getMultiUserChat(roomName)
        muc.addMessageListener(messageListener)

        muc.addMessageListener { message -> Log.e("SmackUtil->", message.body) }
    }

    /**
     * * 注册用户信息 * @param user 账号，是用来登陆用的，不是用户昵称 * @param password 账号密码 * @param
     * attributes 账号其他属性，参考AccountManager.getAccountAttributes()的属性介绍 * @return
     * @throws InterruptedException
     * @throws XmppStringprepException
     */
    @Throws(InterruptedException::class, XmppStringprepException::class)
    fun registerUser(user: String, password: String, attributes: Map<String, String>): Boolean {
        if (!connection.isConnected) {
            return false
        }
        try {
            AccountManager.sensitiveOperationOverInsecureConnectionDefault(true)
            //Localpart l_username = Localpart.from(user);
            AccountManager.getInstance(connection).createAccount(user, password, attributes)
            return true
        } catch (e: NoResponseException) {
            return false
        } catch (e: XMPPErrorException) {
            return false
        } catch (e: NotConnectedException) {
            return false
        }

    }

//    companion object {
//
//        @Throws(Exception::class)
//        @JvmStatic
//        fun main(args: Array<String>) {
//            val util = SmackUtil("吕锡乐", "111111", "218.246.5.251", 5222)
//            //Map<String, String> attributes = new HashMap<String, String>();
//            //util.registerUser("supermaneXXFF", "111111",attributes);
//            util.createChatRoom("吕锡乐测试房间", "吕锡乐", "")
//            //util.disConnented();
//        }
//    }

}
